package it.paspiz85.nanobot.ui; import it.paspiz85.nanobot.util.Settings; import java.util.Date; import java.util.logging.Formatter; import java.util.logging.Handler; import java.util.logging.LogRecord; import java.util.logging.Logger; import javafx.application.Platform; import javafx.scene.control.TextArea; /** * Handler for logging in a textarea on GUI. * * @author paspiz85 * */ public class LogHandler extends Handler { /** * Doing basically what <code>SimpleFormatter</code> does. Java does not let * you have two different formats for <code>SimpleFormatter</code>. <br> * Not only that, there is also no way to utilize * <code>SimpleFormatter.format()</code> method * * @author paspiz85 */ private static class LogFormatter extends Formatter { private static final String FORMAT = "[%1$tm.%1$td.%1$ty %1$tl:%1$tM:%1$tS %1$Tp] %4$s: %5$s %n"; private final Date date = new Date(); @Override public String format(final LogRecord record) { date.setTime(record.getMillis()); final String message = formatMessage(record); return String.format(FORMAT, date, null, record.getLoggerName(), record.getLevel().getLocalizedName(), message, null); } } private static final long CLEAN_INTERVAL = 60 * 60 * 1000; static void initialize(final TextArea textArea) { for (final Handler h : Logger.getLogger("").getHandlers()) { if (h instanceof LogHandler) { ((LogHandler) h).setTextArea(textArea); } } } private final Formatter formatter = new LogFormatter(); private int lastCleanPosition; private Long lastCleanTime; private TextArea textArea; private synchronized void append(final LogRecord record) { textArea.appendText(formatter.format(record)); final long t = System.currentTimeMillis(); if (lastCleanTime == null || lastCleanTime + CLEAN_INTERVAL < t) { textArea.deleteText(0, lastCleanPosition); lastCleanTime = t; lastCleanPosition = textArea.getLength(); } } @Override public void close() throws SecurityException { this.textArea = null; } @Override public void flush() { } @Override public void publish(final LogRecord record) { if (textArea != null && record.getLevel().intValue() >= Settings.instance().getLogLevel().intValue()) { Platform.runLater(() -> append(record)); } } public void setTextArea(final TextArea textArea) { this.textArea = textArea; } }